package br.com.gscorp.bankLion.controller;


import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import br.com.gscorp.bankLion.dto.MovimentoBancarioDTO;
import br.com.gscorp.bankLion.dto.MovimentoForm;
import br.com.gscorp.bankLion.entity.MovimentoBancario;
import br.com.gscorp.bankLion.entity.TipoOperacao;
import br.com.gscorp.bankLion.entity.Usuario;
import br.com.gscorp.bankLion.exception.UsuarioException;
import br.com.gscorp.bankLion.repository.MovimentoRepository;
import br.com.gscorp.bankLion.repository.UsuarioRepository;
import br.com.gscorp.bankLion.security.AuthorityConstant;
import br.com.gscorp.bankLion.security.BankLionSecurityContext;

@Controller
@Transactional
@RequestMapping("/movimento")
public class MovimentoController {
	
	@Autowired
	private	MovimentoRepository repository;
	
	@Autowired
	private UsuarioRepository usuarioRepository;
	
	@RequestMapping(method=RequestMethod.POST)
	@ResponseBody
	@ResponseStatus(value = HttpStatus.CREATED)
	public MovimentoBancario salvar(@Valid @ModelAttribute MovimentoForm form) {
		MovimentoBancario movimento = new MovimentoBancario();
		
		movimento.setOperacao(form.getOperacao());
		movimento.setObservacao(form.getObservacao());
		movimento.setValor(form.getValor());
		movimento.setAtivo(true);
		movimento.setUsuario(usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId()));
		
		return repository.save(movimento);
	}

	@RequestMapping(value="/{id}", method=RequestMethod.PUT)
	@ResponseBody
	public MovimentoBancario editar(@Valid @ModelAttribute MovimentoForm form, @PathVariable("id") Long id) {
		MovimentoBancario movimento = repository.findByUsuarioAndId(usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId()), id);
		
		movimento.setOperacao(form.getOperacao());
		movimento.setObservacao(form.getObservacao());
		movimento.setValor(form.getValor());
		
		return repository.save(movimento);
	}
	
	@RequestMapping(value="/listarCalculado", method=RequestMethod.GET)
	@ResponseBody
	public MovimentoBancarioDTO listarCalculado() {
		Usuario usuario = usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId());
		List<MovimentoBancario> movimentos = repository.findByUsuario(usuario);
		return calculaGastosEGanhos(movimentos, usuario);
	}

	@RequestMapping(method=RequestMethod.GET)
	@ResponseBody
	public List<MovimentoBancario> listar() {
		return (List<MovimentoBancario>) repository.findByUsuario(usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId()));
	}
	
	@RequestMapping(value="/{id}", method=RequestMethod.GET)
	@ResponseBody
	public MovimentoBancario recuperar(@PathVariable("id") Long id) {
		return repository.findByUsuarioAndId(usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId()), id);
	}
	
	@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
	@ResponseBody
	@Secured(value={AuthorityConstant.ROLE_ADMINISTRADOR})
	public void remover(@PathVariable("id") Long id) {
		MovimentoBancario movimento = repository.findByUsuarioAndId(usuarioRepository.findOne(BankLionSecurityContext.getUsuarioLogado().getId()), id);
		
		if(movimento.equals(null)){
			throw UsuarioException.PERMISSAO_NEGADA;
		} else {
			movimento.setAtivo(false);
			repository.save(movimento);
		}
	}
	public MovimentoBancarioDTO calculaGastosEGanhos(List<MovimentoBancario> movimentos, Usuario usuarioLogado){
		MovimentoBancarioDTO movimentosTotalizados = new MovimentoBancarioDTO();
		Double gastoTotal = (double) 0;
		Double ganhoTotal = (double) 0;
		Double saldoAtual = (double) 0;
		
		for(MovimentoBancario movimento: movimentos){
			if(movimento.getOperacao().equals(TipoOperacao.SAQUE) || 
					movimento.getOperacao().equals(TipoOperacao.DEBITO_POR_TRANSFERENCIA) || 
					movimento.getOperacao().equals(TipoOperacao.PAGAMENTO_DE_CONTAS)) {
				
				gastoTotal+= movimento.getValor();
			} else {
				ganhoTotal+= movimento.getValor();
			}
		}
		
		saldoAtual = usuarioLogado.getSaldo() + ganhoTotal - gastoTotal;
		movimentosTotalizados.setMovimentos(movimentos);
		movimentosTotalizados.setGanhoTotal(ganhoTotal);
		movimentosTotalizados.setGastoTotal(gastoTotal);
		movimentosTotalizados.setSaldoAtual(saldoAtual);
		
		return movimentosTotalizados;
	}
}
